home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / TESTSPAR / SCSI.S < prev    next >
Encoding:
Text File  |  2001-02-09  |  18.0 KB  |  670 lines

  1. ;+
  2. ; Edit History
  3. ;
  4. ; May-17-89    ml.    Started this with jwt's SCSI code.
  5. ; Aug-21-89    ml.    Added format code.
  6. ; Nov-17-89    ml.    Only add 8 to byte count on DMA reads, not writes.
  7. ; Dec-04-89    ml.    Always hand-shake last 8 bytes of data when writing
  8. ;            to disk because of hardware counter handling.
  9. ;            Added w4cntout().
  10. ;            (refer to comments at _wrtscsi())
  11. ; Jan-23-90    ml.    Undid modifications done on Dec-04-89.
  12. ;            (refer to comments at _wrtscsi())
  13. ; Jul-31-90    ml.    Modified to handle vectored-interrupts in addition
  14. ;            to polling. (in form of conditional assembly)
  15. ; Apr-04-91    ml.    Added recalibration time to timeout for transfer of
  16. ;            data. (in w4int() and w4dreq())
  17. ;-
  18.  
  19.  
  20. .include    "defs.h"
  21. .include    "sysvar.h"
  22. .include    "mfp.h"
  23. .include    "scsi.h"
  24. .include    "68030.s"
  25.  
  26. ;+
  27. ; Command length
  28. ;-
  29. NCMD    equ    6        ; length of short command (in bytes)
  30.  
  31.  
  32. .if    VI            ; if vectored-interrupts desired
  33. dmac_int:    dc.b    0    ; flag for DMAC interrupts
  34. phase_changed:    dc.b    0    ; flag for SCSI phase changes
  35. .endif    ;VI
  36.  
  37.  
  38. .if    !DRIVER            ; not to be included in driver
  39. scxltmout:    dc.l    12001    ; SCSI extra long-timeout (>1 min)
  40. slwsclto:    dc.l    5000    ; SCSI long-timeout (>25 S) for stunit()
  41. slwscsto:    dc.l    42    ; SCSI short-timeout (>205 mS) for stunit()
  42. scltmout:    dc.l    201    ; SCSI long-timeout (>1000 ms)
  43. scstmout:    dc.l    101    ; SCSI short-timeout (>500 ms)
  44. rcaltm:        dc.l    801    ; time for drive recalibration (>4s)
  45. .even
  46. .else    ;!DRIVER
  47. .extern    scxltmout, slwsclto, slwscsto, scltmout, scstmout, rcaltm
  48. .endif    ;!DRIVER
  49.  
  50.  
  51. ;+
  52. ; smplscsi() - send a simple SCSI command (ie. no DMA involved)
  53. ;
  54. ;    d0.w = physical unit number
  55. ;    d1.l = transfer length (in bytes)
  56. ;    d2.w = command length (NCMD or LCMD)
  57. ;    a0.l = buffer address
  58. ;-
  59.     .globl    _smplscsi
  60. _smplscsi:
  61.     andi.w    #7,d0            ; mask off the flags to get unit num
  62.     bsr    sblkscsi        ; send command block
  63.     bpl.s    .0            ; if successful, wait for status
  64.     rts                ; else return
  65. .0:    bra    w4stat            ; waiting for status byte
  66.  
  67.  
  68. ;+
  69. ; rcvscsi() - send a SCSI command which receives data back.
  70. ;
  71. ; Passed:
  72. ;    d0.w = physical unit number
  73. ;    d1.l = transfer length (in bytes)
  74. ;    d2.w = command length (NCMD or LCMD)
  75. ;    a0.l = buffer address
  76. ;
  77. ; Comments:
  78. ;    The code that checks whether there is data left in the residue
  79. ; register does not work for some transfers of less than 4 bytes to a
  80. ; non-longword aligned address.  
  81. ;-
  82.     .globl    _rcvscsi
  83. _rcvscsi:
  84. .if    !SCDMA                ; if not doing DMA
  85.     move.l    a0,-(sp)        ; save buffer address
  86. .endif    ;SCDMA
  87.     andi.w    #7,d0            ; mask off the flags to get unit num
  88.  
  89. .if    SCDMA                ; if doing DMA
  90. .if    ODMA                ; and using Old DMA controller
  91.     addq.l    #8,d1            ; add 8 because of hardware bug
  92. .endif    ;ODMA
  93. .endif    ;SCDMA
  94.  
  95.     move.w    d2,-(sp)        ; save the command length
  96.     bsr    sblkscsi        ; send command block
  97.     move.w    (sp)+,d2        ; restore the command length
  98. .if    !SCDMA                ; if not doing DMA
  99.     move.l    (sp)+,a0        ; restore buffer address
  100. .endif    ;SCDMA
  101.     tst.w    d0            ; successful?
  102.     bmi    rsend            ; if not successful, return
  103.  
  104.     move.b    #0,SCSIICR        ; deassert the data bus
  105.     move.b    #1,SCSITCR        ; set data in phase
  106.     move.b    SCSIREI,d0        ; clear potential interrupt
  107.  
  108. .if    SCDMA
  109.                     ; Set up the DMAC for data transfer
  110.     move.b    #2,SCSIMR        ; enable DMA mode
  111.     move.b    #0,SCSIDIR        ; start the DMA receive
  112.     move.w    #DMAIN,SDMACTL        ; set the DMAC direction to IN
  113.     move.w    #DMAIN+DMAENA,SDMACTL    ; turn on DMAC
  114.  
  115.     bsr    setscstmout        ; set up a short timeout
  116.     cmpi.w    #NCMD,d2        ; is this a long command?
  117.     beq.s    .0            ; if not, just go on
  118.     bsr    setscxltmout        ; else, set up an extra long timeout
  119. .0:    bsr    w4int            ; wait for interrupts
  120.     tst.w    d0            ; successful?
  121.     bne.s    rsend            ; if error, returns
  122.     bsr    w4stat            ; wait for status byte
  123.     tst.w    d0            ; successful?
  124.     bne.s    rsend            ; if error, returns
  125.     move.l    d0,-(sp)        ; else save returned status
  126.  
  127.     move    sr,-(sp)        ; go to IPL 7
  128.     ori    #$700,sr        ; no interrupts right now kudasai
  129.     movecacrd0            ; d0 = (cache control register)
  130.     ori.w    #$808,d0        ; dump both the D and I cache
  131.     moved0cacr            ; update cache control register
  132.     move    (sp)+,sr        ; restore interrupt state
  133.  
  134.     move.b    bSDMAPTR+6,d0        ; see if this was an odd transfer
  135.     andi.w    #3,d0            ; (ie, not multiple of 4)
  136.     beq.s    .2            ; no, nice and even (and easy)
  137.  
  138.     movea.l    #bSDMAPTR,a1        ; a1 -> DMA address
  139.     movep.l    (0,a1),d0        ; d0 = current value of DMA pointer
  140.     move.l    d0,d1            ; d1 = current value of DMA pointer
  141.  
  142.     andi.w    #3,d0            ; # bytes left in residue register
  143.     andi.w    #$FFFF-3,d1        ; where does data go to?
  144.     movea.l    d1,a0            ; a0 -> where rest of data should go
  145.     move.l    SDMARES,d1        ; get the residue
  146.     subq.w    #1,d0            ; dbra likes one less than count
  147. .1:    rol.l    #8,d1            ; tranfer residue to buffer
  148.     move.b    d1,(a0)+
  149.     dbra    d0,.1
  150.  
  151. .2:    move.l    (sp)+,d0        ; recall the status byte
  152.  
  153. .else    ;SCDMA
  154.     movea.l    a0,a1            ; a1 -> buffer to read into
  155.     movea.l    #bSCSI,a2        ; a2 -> 5380
  156. .3:    bsr    setscstmout
  157.     bsr    w4dreq            ; wait for REQ for data to come
  158.     bmi.s    rsend            ; if timed out, returns
  159.     btst    #3,5*REGSTEP(a2)    ; still in data in phase?
  160.     beq    w4stat            ; no, go get status
  161.     move.b    (a2),(a1)+        ; read the data byte
  162.     bsr    doack
  163.     bra.s    .3            ; do next byte
  164. .endif    ;SCDMA
  165. rsend:    rts
  166.  
  167.  
  168. ;+
  169. ; wrtscsi() - send a SCSI command which will write data to the target
  170. ;
  171. ; Passed:
  172. ;    d0.w = physical unit number
  173. ;    d1.l = transfer length (in bytes)
  174. ;    d2.w = command length (NCMD or LCMD)
  175. ;    a0.l = buffer address
  176. ;
  177. ; Comments: 
  178. ; 12/04/89 ml
  179. ;    Bus error occurs when doing a write to the disk that ends at top
  180. ; of memory.  The DMA counter is decremented when the bytes are written 
  181. ; from the ping pong buffers to the device, not when bytes are grapped 
  182. ; from RAM to the ping pong buffers.  Well, AFTER the last 8 bytes are 
  183. ; read into the ping pong buffers and BEFORE they are written to the 
  184. ; device, the chip will attempt to read the NEXT 8 bytes into the ping 
  185. ; pong buffers which results in a bus error because it will be reading 
  186. ; pass top of memory.  To get around this HARDWARE BUG, the code will 
  187. ; ALWAYS handshake the last 8 bytes over instead of DMAing them.
  188. ;
  189. ; 01/23/90 ml
  190. ;    A. Pratt said he's willing to move the screen down and sacrifice
  191. ; 16 bytes of memory.  So, code added on 12/04/89 is commented out.
  192. ;-
  193.     .globl    _wrtscsi
  194. _wrtscsi:
  195.     andi.w    #7,d0            ; mask off the flags to get unit num
  196.  
  197. .if    !SCDMA
  198.     move.l    a0,-(sp)        ; save beginning buffer address
  199. .endif    ;!SCDMA
  200.  
  201. .0:    move.w    d2,-(sp)        ; save command length
  202.     bsr    sblkscsi        ; send command block
  203.     move.w    (sp)+,d2        ; restore command length
  204. .if    !SCDMA
  205.     move.l    (sp)+,a0        ; a0 = where DMA ends
  206. .endif    ;!SCDMA
  207.     tst.w    d0            ; successful?
  208.     bpl.s    .1            ; if successful, go on
  209.     rts                ; else return
  210.  
  211. .1:    move.b    #0,SCSITCR        ; set data out phase
  212.     move.b    SCSIREI,d0        ; clear potential interrupt
  213.  
  214. .if    SCDMA
  215.                     ; Set up the DMAC for data transfer
  216.     move.b    #2,SCSIMR        ; enable DMA mode
  217.     move.b    #0,SCSIDS        ; start the DMA send
  218.     move.w    #DMAOUT,SDMACTL        ; set the DMAC direction
  219.     move.w    #DMAOUT+DMAENA,SDMACTL    ; turn on DMAC
  220.  
  221.     bsr    setscstmout        ; set up a short timeout
  222.     cmpi.w    #NCMD,d2        ; is this a long command?
  223.     beq.s    .2            ; if not, just go on
  224.     bsr    setscxltmout        ; set up an extra long timeout
  225. .2:    bsr    w4int            ; wait for interrupts
  226.     tst.w    d0
  227.     bne.s    wsend            ; if failed, return
  228.     bsr    w4stat            ; wait for status byte
  229.  
  230. .else    ;SCDMA
  231.                     ; hand shake the rest over the bus
  232.     movea.l    a0,a1            ; a1 -> buffer to write from
  233.     movea.l    #bSCSI,a2        ; a2 -> 5380
  234. .3:    bsr    setscstmout
  235.     bsr    w4dreq            ; wait for REQ for data to come
  236.     bmi.s    wsend            ; if timed out, returns
  237.     btst    #3,5*REGSTEP(a2)    ; still in data out phase?
  238.     beq    w4stat            ; no, go get status
  239.     move.b    (a1)+,(a2)        ; write the data byte
  240.     bsr    doack
  241.     bra.s    .3            ; do next byte
  242. .endif    ;SCDMA
  243. wsend:    rts
  244.  
  245.  
  246.  
  247. ;+
  248. ; sblkscsi() - set DMA pointer and count and send command block
  249. ;
  250. ; Passed:
  251. ;    d0.w = physical unit number
  252. ;    d1.l = transfer length (in bytes)
  253. ;    d2.w = command length (NCMD or LCMD)
  254. ;    a0.l = buffer address
  255. ;
  256. ; Returns:
  257. ;    d0.l =  0 if successful
  258. ;    d0.l = -1 if timeout
  259. ;-
  260.     .extern    _cmdblk
  261. sblkscsi:
  262.     movem.l    d1-d2/a0,-(sp)        ; preserve d1, d2 and a0
  263.     move.w    d0,-(sp)        ; physical unit #
  264.     bsr    selscsi            ; select the unit
  265.     addq.l    #2,sp            ; clean up stack
  266.     movem.l    (sp)+,d1-d2/a0        ; restore d1, d2 and a0
  267.     tst.w    d0            ; selection successful?
  268.     bmi.s    sbsend            ; if timed out, return
  269.                     ; else proceed
  270. .if    SCDMA
  271.     move.l    a0,d0            ; d0 = buffer address
  272.     movea.l    #bSDMAPTR,a1        ; a1 -> DMA address
  273.     movep.l    d0,(0,a1)        ; set DMA pointer
  274.  
  275.     movea.l    #bSDMACNT,a1        ; a1 -> DMA count
  276.     movep.l    d1,(0,a1)        ; set DMA count
  277. .endif    ;SCDMA
  278.  
  279.     move.b    #2,SCSITCR        ; assert C/D
  280.     move.b    #1,SCSIICR        ; assert data bus
  281.  
  282.     bsr    setscstmout        ; set up timeout for sending cmdblk
  283.     lea    _cmdblk,a1        ; a1 -> command block
  284.     subq.w    #1,d2            ; dbra likes one less
  285. .0:    move.b    (a1)+,d0        ; d0.b = byte to be sent
  286.     bsr    hshake            ; write that byte
  287.     tst.w    d0
  288.     bmi.s    sbsend            ; if timed-out, returns
  289.     dbra    d2,.0            ; until whole command block is sent
  290.     moveq    #0,d0            ; all operations successful
  291. sbsend: rts                ; heading home
  292.  
  293.  
  294. ;+
  295. ; BOOLEAN selscsi(SCSIUnit) 
  296. ; WORD SCSIUnit;
  297. ;-
  298. selscsi:
  299.     bsr    setscstmout        ; set up a short timeout
  300. .0:    btst    #6,SCSICR        ; STILL busy from last time?
  301.     beq.s    .1            ; if not, it's available
  302.     cmp.l    (a0),d1            ; timeout?
  303.     bhi.s    .0            ; not yet, wait some more
  304.     bra.s    .3            ; else, return error
  305.  
  306. .1:    move.b    #0,SCSITCR        ; data out phase
  307.     move.b    #0,SCSIISR        ; no interrupt from selection
  308.     move.b    #$0c,SCSIICR        ; assert BSY and SEL
  309. ; set dest SCSI IDs
  310.     clr.w    d0
  311.     move.w    4(sp),d1        ; get the SCSI unit desired
  312.     bset    d1,d0            ; set the appropriate bit
  313.     move.b    d0,SCSIODR        ; (real code would set ours too)
  314.  
  315.     move.b    #$0d,SCSIICR        ; assert BUSY, SEL and data bus
  316.     andi.b    #$FE,SCSIMR        ; clear arbitrate bit
  317.     andi.b    #$F7,SCSIICR        ; clear BUSY
  318.     nop                ; 2 deskew delays
  319.     nop
  320.  
  321.     bsr    setscstmout        ; set up for timeout
  322. .2:    btst    #6,SCSICR        ; wait for bus to be busy
  323.     bne.s    .4
  324.     cmp.l    (a0),d1
  325.     bhi.s    .2
  326.  
  327. .3:    moveq    #-1,d0            ; time out
  328.     bra.s    .5
  329.     
  330. .4:    clr.w    d0            ; selection successful
  331. .5:    move.b    #$0,SCSIICR        ; clear SEL and data bus assertion
  332.     rts
  333.  
  334.  
  335. *+
  336. * VOID resetscsi();
  337. *-
  338.     .globl    resetscsi
  339. resetscsi:
  340.     move.b    #$80,SCSIICR    ; assert RST
  341.     bsr    setscstmout    ; wait (at least) 250 ms
  342. .0:    cmp.l    (a0),d1
  343.     bhi.s    .0
  344.     move.b    #$00,SCSIICR
  345.     bsr    setscltmout    ; wait (at least) 1000 ms
  346. .1:    cmp.l    (a0),d1
  347.     bhi.s    .1
  348.     rts
  349.  
  350.  
  351. ;+
  352. ; w4int - wait for interrupts from 5380 or DMAC during DMA tranfers
  353. ;
  354. ; Passed:
  355. ;    d1.l = expiration time
  356. ;    a0.l = address of _hz_200
  357. ;
  358. ; Returns:
  359. ;    d0.l = returned status or timeout error
  360. ;
  361. ; Comments:
  362. ;    When 5380 is interrupted, it indicates a change of data to
  363. ; status phase (i.e., DMA is done), or ...
  364. ;    When DMAC is interrupted, it indicates either DMA count is
  365. ; zero, or there is an internal bus error.
  366. ;-
  367. w4int:    
  368.     add.l    rcaltm,d1        ; add time for recalibration
  369. .0:    
  370. .if    VI
  371.     tst.b    phase_changed        ; phase changed?
  372. .else    ;VI
  373.     btst    #GPIP2SCSI,GPIP2    ; wait for 5380 to interrupt
  374. .endif    ;VI
  375.  
  376.     bne.s    .3            ; active HIGH
  377.     cmp.l    (a0),d1            ; time's up yet?
  378.     bls.s    .4            ; if not, wait some more
  379.  
  380. .if    VI
  381.     tst.b    dmac_int        ; DMAC interrupted?
  382.     bne.s    .1            ; if so, check out why
  383. .else    ;VI
  384.     btst    #5,GPIP2        ; or for DMAC to interrupt
  385.     beq.s    .1            ; active LOW
  386. .endif    ;VI
  387.  
  388.     cmp.l    (a0),d1            ; time's up yet?
  389.     bhi.s    .0            ; if not, wait some more
  390.                     ; timed-out
  391. .4:    bsr    resetscsi        ; reset the SCSI bus
  392.     moveq    #-1,d0            ; else, return timeout
  393.     bra.s    w4iend
  394.  
  395. .1:    move.w    SDMACTL,d0        ; get the DMAC status
  396.     andi.l    #$80,d0            ; check for bus err/ignore cntout ints
  397.  
  398. .if    VI
  399.     bne.s    .2            ; if bus error reset bus
  400.     sf    dmac_int        ; else clear dmac interrupt flag
  401.     bra.s    .0            ; and wait some more
  402. .else    ;VI
  403.     beq.s    .0            ; if fine, wait for interrupts again
  404. .endif    ;VI
  405.  
  406. .2:    move.w    d0,-(sp)        ; save the returned status
  407.     bsr    resetscsi        ; reset the SCSI bus
  408.     move.w    (sp)+,d0        ; d0 = return code
  409.  
  410. .if    VI
  411.     sf    dmac_int        ; clear dmac interrupt flag
  412. .endif    ;VI
  413.  
  414.     bra.s    w4iend            ; returns
  415. .3:    
  416. .if    VI
  417.     sf.b    phase_changed        ; clear phase change flag
  418.     move.b    SCSICR,d0        ; d0 = SCSI control register
  419.     andi.b    #$1c,d0            ; mask off irrelevant bits
  420.     cmpi.b    #$c,d0            ; data phase -> status phase?
  421.     bne.s    .0            ; if not, wait some more
  422. .endif    ;VI
  423.  
  424.     moveq    #0,d0            ; DMA is successful
  425.     move.b    SCSIREI,d1        ; clear potential interrupt
  426.     move.w    #DMADIS,SDMACTL        ; disable DMA
  427.     move.b    #0,SCSIMR        ; disable DMA mode
  428.     move.b    #0,SCSIICR        ; make sure data bus is not asserted
  429. w4iend:    rts
  430.  
  431.  
  432. ;+
  433. ; w4stat - wait for status byte and message byte.
  434. ;
  435. ; Returns:
  436. ;    d0.l = returned status or timeout error
  437. ;-
  438. w4stat:    bsr    setscstmout        ; set up time-out for REQ and ACK
  439.     move.b    #3,SCSITCR        ; status in phase
  440.     move.b    SCSIREI,d0        ; clear potential interrupt
  441.  
  442.     bsr    w4req            ; wait for status byte
  443.     bmi.s    w4send            ; if timed-out, returns
  444. gstat:    moveq    #0,d0            ; clear d0
  445.     move.b    SCSIDB,d0        ; get the status byte
  446.     move.l    d0,-(sp)        ; save the status byte
  447.     bsr    setscstmout        ; set up time-out for REQ and ACK
  448.     bsr    doack            ; signal that status byte is here
  449.     tst.w    d0            ; timed-out?
  450.     beq.s    .1            ; if not, wait for message byte
  451.  
  452. .0:    addq.l    #4,sp            ; else clean up stack
  453.     bra.s    w4send            ; and return
  454.  
  455. .1:    bsr    setscstmout        ; set up timeout for REQ and ACK
  456.     bsr    w4req            ; wait for message byte
  457.     bmi.s    .0            ; if timed-out, returns
  458.  
  459.     move.b    SCSIDB,d0        ; get and ignore message byte
  460.     bsr    doack            ; signal that message byte is here
  461.     tst.w    d0            ; timed-out?
  462.     bmi.s    .0            ; if so, return timeout
  463.  
  464. .if    DEBUG
  465.     move.l    #_hz_200,a0        ; For debugging SEA177N - 
  466.     moveq    #4,d1            ;   add a delay after receiving 
  467.     add.l    (a0),d1            ;   message byte
  468. .2:    cmp.l    (a0),d1
  469.     bhi.s    .2
  470. .endif    ;DEBUG
  471.  
  472.     move.l    (sp)+,d0        ; recall the status byte
  473. w4send:    rts
  474.  
  475.  
  476. ;+
  477. ; w4dreq() - wait for REQ to come during hand shake of data bytes
  478. ; w4req() - wait for REQ to come during hand shake of non-data bytes
  479. ;
  480. ; Passed:
  481. ;    d1.l = expiration time
  482. ;    a0.l = address of _hz_200
  483. ;
  484. ; Returns:
  485. ;     0 - if successful
  486. ;    -1 - times out
  487. ;-
  488. w4dreq:    add.l    rcaltm,d1        ; add time for recalibration
  489. w4req:
  490. .0:    btst    #5,SCSICR        ; waiting for REQ to come
  491.     bne.s    .1            ; if REQ comes, done
  492.     cmp.l    (a0),d1            ; time's up?
  493.     bhi.s    .0            ; if not, wait some more
  494.     moveq    #-1,d0            ; else, returns timed out
  495.     bra.s    w4rend
  496. .1:    moveq    #0,d0            ; returns successful
  497. w4rend:    rts
  498.  
  499.  
  500. ;+
  501. ; doack() - assert ACK
  502. ;
  503. ; Passed:
  504. ;    d1.l = expiration time
  505. ;    a0.l = address of _hz_200
  506. ;
  507. ; Returns:
  508. ;     0 - if successful
  509. ;    -1 - times out
  510. ;-
  511. doack:    ori.b    #$11,SCSIICR        ; assert ACK (and data bus)
  512. .0:    btst    #5,SCSICR        ; wait for REQ to go away
  513.     beq.s    .1            ; if REQ goes away, done
  514.     cmp.l    (a0),d1            ; time's up?
  515.     bhi.s    .0            ; if not, wait some more
  516.     moveq    #-1,d0            ; else returns timed out
  517.     bra.s    doaend
  518. .1:    moveq    #0,d0            ; returns successful
  519. doaend:    andi.b    #$ef,SCSIICR        ; clear ACK
  520.     rts
  521.  
  522.  
  523. ;+
  524. ; hshake() - hand shake a byte over to the controller
  525. ;
  526. ; Passed:
  527. ;    d0.b = byte to be handed over
  528. ;    d1.l = expiration time
  529. ;    a0.l = address of _hz_200
  530. ;
  531. ; Returns:
  532. ;    Whatever w4req() or doack() returns, which is:
  533. ;         0 - if successful
  534. ;        -1 - times out
  535. ;-
  536. hshake:    move.w    d0,-(sp)        ; preserve d0.w
  537.     bsr    w4req            ; wait for REQ to come
  538.     bmi.s    hsend            ; if timed out, returns
  539.     move.b    1(sp),SCSIDB        ; write a byte out to data bus
  540.     bsr    doack            ; assert ACK
  541. hsend:    addq.l    #2,sp            ; clean up stack
  542.     rts
  543.  
  544.  
  545. ;+
  546. ; setscstmout - set up a timeout count for the SCSI for SCSTMOUT long
  547. ;
  548. ; Returns:
  549. ;    a0.l = address of _hz_200 clock
  550. ;    d1.l = expiration time
  551. ;-
  552.     .globl    setscstmout
  553. setscstmout:
  554.     movea.l    #_hz_200,a0        ; a0 -> 200 hz clock
  555.     move.l    scstmout,d1        ; d0 = scstmout _hz_200 clicks
  556.     add.l    (a0),d1            ; d0 = curr time + # clicks to wait
  557.     rts
  558.  
  559.  
  560. ;+
  561. ; setscltmout - set up a timeout count for the SCSI for SCLTMOUT long
  562. ;
  563. ; Returns:
  564. ;    a0.l = address of _hz_200 clock
  565. ;    d1.l = expiration time
  566. ;-
  567.     .globl    setscltmout
  568. setscltmout:
  569.     movea.l    #_hz_200,a0        ; a0 -> 200 hz clock
  570.     move.l    scltmout,d1        ; d0 = scltmout _hz_200 clicks
  571.     add.l    (a0),d1            ; d0 = curr time + # clicks to wait
  572.     rts
  573.  
  574.  
  575. ;+
  576. ; setscxltmout - set up a timeout count for the SCSI for SCXLTMOUT long
  577. ;
  578. ; Returns:
  579. ;    a0.l = address of _hz_200 clock
  580. ;    d1.l = expiration time
  581. ;-
  582.     .globl    setscxltmout
  583. setscxltmout:
  584.     movea.l    #_hz_200,a0        ; a0 -> 200 hz clock
  585.     move.l    scxltmout,d1        ; d0 = scxltmout _hz_200 clicks
  586.     add.l    (a0),d1            ; d0 = curr time + # clicks to wait
  587.     rts
  588.  
  589.  
  590.  
  591. .if    !DRIVER                ; not to be included in driver
  592.  
  593. ;+
  594. ; fmtscsi() - format a SCSI unit
  595. ;
  596. ;    d0.w = physical unit number
  597. ;    d1.l = transfer length (in bytes)
  598. ;    d2.w = command length (NCMD or LCMD)
  599. ;    a0.l = buffer address
  600. ;-
  601.     .globl    _fmtscsi
  602. _fmtscsi:
  603.     andi.w    #7,d0            ; mask off the flags to get unit num
  604.     bsr    sblkscsi        ; send command block
  605.     bpl.s    .0            ; if successful, wait for status byte
  606.     rts                ; else return
  607. .0:    move.b    #3,SCSITCR        ; status in phase
  608.     move.b    SCSIREI,d0        ; clear potential interrupt
  609. .1:    btst    #5,SCSICR        ; wait forever for REQ to 
  610.  
  611.  
  612. .if    DEBUG
  613.  
  614.     bne.s    .3            ; For debugging purpose - 
  615.     move.l    #_hz_200,a0        ;    add a delay in this "tight" 
  616.     moveq    #2,d1            ;    loop to slow down SCSI chip 
  617.     add.l    (a0),d1            ;    accessing.
  618. .2:    cmp.l    (a0),d1
  619.     bhi.s    .2
  620.     bra.s    .1
  621.  
  622. .else    ;DEBUG
  623.  
  624.     beq.s    .1            ;   come
  625.  
  626. .endif    ;DEBUG
  627.  
  628. .3:    bra    gstat            ; when REQ comes, get status byte
  629.  
  630. .endif    ;!DRIVER
  631.  
  632.  
  633. .if    VI
  634. ;+
  635. ; scsi_isr - interrupt service routine for SCSI phase changes
  636. ;-
  637.     .globl    scsi_isr
  638. scsi_isr:
  639.     movem.l    d0-d1,-(sp)        ; save d0 and d1
  640.     move.b    SCSIDSR,d0        ; read DMA status register
  641.     move.b    d0,d1            ; d0 and d1 contains DMA status
  642.     andi.b    #$10,d0            ; interrupt coming from IRQ
  643.     beq.s    scsiend            ; if not, not interested
  644.     andi.b    #$2c,d1            ; else mask off irrelevant bits
  645.     cmpi.b    #$1f,d1            ; if status > 0x1f
  646.     bhi.s    scsiend            ;   ignore parity error interrupt
  647.     btst.l    #$3,d1            ; phase match bit cleared?
  648.     bne.s    scsiend            ; if not, not interested
  649.                     ; else it's a phase mismatch interrupt
  650.     st    phase_changed        ; set flag to indicate phase changes
  651. scsiend:
  652.     movem.l    (sp)+,d0-d1        ; restore d0 and d1
  653.     move.b    #$7f,ISRA2        ; clear GPIP2SCSI in-service bit
  654.     rte
  655.  
  656.  
  657.  
  658. ;+
  659. ; dmac_isr - interrupt service routine for DMAC
  660. ;    It means we are either a cntout zero or internal bus error.
  661. ;-
  662.     .globl    dmac_isr
  663. dmac_isr:
  664.     st    dmac_int        ; indicate DMAC was interrupted
  665.     move.b    #$7f,ISRB2        ; clear GPIP25 in-service bit 
  666.     rte
  667.  
  668. .endif    ;VI
  669.  
  670.